class lazy_property(object):
    """  only evaluated once """

    def __init__(self, deferred):
        self._deferred = deferred
        self.__doc__ = deferred.__doc__

    def __get__(self, obj, cls):
        if obj is None:
            return self

        value = self._deferred(obj)
        setattr(obj, self._deferred.__name__, value)
        return value


if __name__ == "__main__":
    class A:
        @lazy_property
        def get_abc(self):
            print("abc")

    a = A()
    a.get_abc
    a.get_abc
    a.get_abc
